
#ifndef SEMANTIC_ANALYZER_H

#define SEMANTIC_ANALYZER_H

#include "semantics_namespace.h"
#include "semantics_expression.h"
#include "semantics_simulation.h"
#include "semantics_context.h"
#include "semantics_method.h"
#include "semantics_model.h"
#include "semantics_simulation.h"
#include "syntax_tree.h"
#include "lexic_units.h"


class SemanticAnalyzer
{
public:
	SemanticAnalyzer();
	~SemanticAnalyzer();


	SemanticsNamespace * RootNamespace;

	// F stands for Flat :)
	GenericTable<SemanticsClass> * FClasses;
	GenericTable<SemanticsField> * FFields;
	GenericTable<SemanticsFieldSingle> * FSingleFields; // special!
	GenericTable<SemanticsProperty> * FProperties;
	GenericTable<SemanticsEnum> * FEnums;
	GenericTable<SemanticsMethod> * FMethods;
	GenericTable<SemanticsModel> * FModels;
	GenericTable<SemanticsSimulation> * FSimulations;


	// GATHER 
	void Gather();

	// FLATTEN HIERARCHY
	void FlattenHierarchy();

	void FlattenFromNamespace(SemanticsNamespace * currentNamespace);
	void FlattenFromClass(SemanticsClass * currentClass);
	void FlattenFromMultField(SemanticsField * currentField);

	// FILL NAMES
	void FillNames();

	
	// assisting methods
	void CopyNames(GenericTable<int> * source, GenericTable<int> * destination);



	// SEMANTIC VERIFICATION
	void Verify();



	// CODE GENERATION
	void GenerateCode();




	void GatherFromFileBody(SyntaxTreeNode * nodeFileBody, int parentContext, SemanticsNamespace * parentNamespace);
	
	void GatherFromMainDefinition(SyntaxTreeNode * nodeMainDefinition, int parentContext, SemanticsNamespace * parentNamespace);
	
	// READ MAIN PROGRAM PARTS
	SemanticsClass * GatherFromClass(SyntaxTreeNode * nodeClass, int parentContext);
	SemanticsNamespace * GatherFromNamespace(SyntaxTreeNode * nodeNamespace, int parentContext);
	SemanticsEnum * GatherFromEnum(SyntaxTreeNode * nodeEnum, int parentContext);
	SemanticsModel * GatherFromModel(SyntaxTreeNode * nodeModel, int parentContext);
	SemanticsMethod * GatherFromMethod(SyntaxTreeNode * nodeMethod, int parentContext);
	SemanticsField * GatherFromField(SyntaxTreeNode * nodeField, int parentContext);
	SemanticsProperty * GatherFromProperty(SyntaxTreeNode * nodeProperty, int parentContext);
	SemanticsSimulation * GatherFromSimulation(SyntaxTreeNode * simulationNode, int parentContext);
	SemanticsExpression * GatherFromExpression2(SyntaxTreeNode * expressionNode);
	SemanticsExpression * GatherFromExpressionAdds(SyntaxTreeNode * expressionNode);

	int GatherArrayDimensionsCount(SyntaxTreeNode * arrayDeclarationNode);

// ??????????? - unknown yet - TODO
	SemanticsExpression * GatherFromExpression(SyntaxTreeNode * expressionNode);

	// TODO - emergency
	SemanticsDataType * GatherFromDataType(SyntaxTreeNode * dataTypeNode);


	// read both <name> and NAME
	GenericTable<int> * GatherFromNameNode(SyntaxTreeNode * nameNode);

	// read enumeration members
	GenericTable<int> * GatherFromEnumMembersNode(SyntaxTreeNode * enumNamesNode);
	
	// read parameters
	GenericTable<SemanticsMethodParameter> * GatherParameters(SyntaxTreeNode * parametersNode);
	GenericTable<SemanticsMethodParameter> * ReadMethodParameters(SyntaxTreeNode * msParametersNode);

	// read model block labels
	GenericTable<int> * ReadModelBlockLabels(SyntaxTreeNode * modelBlockLabelsNode);

	// read model definition in and out labels
	GenericTable<int> * GatherLabels(SyntaxTreeNode * labelListNode);

	// FOR METHODS: ReadMS -> ReadMethodStatement
	SemanticsMethodStatement * ReadMethodStatement(SyntaxTreeNode * methodStatementNode);

	SemanticsMethodBody * ReadMethodBody(SyntaxTreeNode * methodBodyNode);

	SemanticsMethodStatementAssignment * ReadMSAssignment(SyntaxTreeNode * msAssignmentNode);
	SemanticsMethodStatementMethodCall * ReadMSMethodCall(SyntaxTreeNode * msMethodCallNode);
	SemanticsMethodStatementIf * ReadMSIf(SyntaxTreeNode * msIfNode);
	SemanticsMethodStatementWhile * ReadMSWhile(SyntaxTreeNode * msWhileNode);
	SemanticsMethodStatementFor * ReadMSFor(SyntaxTreeNode * msForNode);
	SemanticsMethodStatementDoWhile * ReadMSDoWhile(SyntaxTreeNode * msDoWhileNode);
	SemanticsMethodStatementCase * ReadMSCase(SyntaxTreeNode * msCaseNode);
	SemanticsMethodStatementSwitchCase * ReadMSSwitchCase(SyntaxTreeNode * msSwitchCaseNode);
	SemanticsMethodStatementBreak * ReadMSBreak(SyntaxTreeNode * msBreakNode);
	SemanticsMethodStatementContinue * ReadMSContinue(SyntaxTreeNode * msContinueNode);
	SemanticsMethodStatementGoto * ReadMSGoto(SyntaxTreeNode * msGotoNode);
	SemanticsMethodStatementReturn * ReadMSReturn(SyntaxTreeNode * msReturnNode);
	SemanticsMethodStartAssignment * ReadMSStartAssignment(SyntaxTreeNode * msStartAssignmentNode);
	SemanticsMethodStatementStart * ReadMSStart(SyntaxTreeNode * msStartNode);
	SemanticsMethodStatementStop * ReadMSStop(SyntaxTreeNode * msStopNode);
	SemanticsMethodStatementDerivationAssignment * ReadMSDerivationAssignment(SyntaxTreeNode * msDerivationAssignmentNode);
	SemanticsMethodParameter * ReadMethodParameter(SyntaxTreeNode * msParameterNode);
	SemanticsMethodValuePair * ReadMethodValuePair(SyntaxTreeNode * msValuePair);




	// FOR MODELS: ReadMB -> ReadModelBlock
	SemanticsModelBodyDefine * GatherFromModelBodyDefine(SyntaxTreeNode * modelDefineNode, int parentContext);
	SemanticsModelStructure * GatherFromModelStructure(SyntaxTreeNode * modelStructureNode, int parentContext);

	SemanticsModelBlock * ReadModelBlock(SyntaxTreeNode * modelBlockNode); // ????

    GenericTable<SemanticsBlockTransactionDetail> * GatherFromTransactionListNode(SyntaxTreeNode * transactionListNode); /// ???
	SemanticsBlockTransactionDetail * ReadMBTransactionDetail(SyntaxTreeNode * transactionDetailNode); /// ???

	SemanticsBlockGenerate * ReadMBGenerate(SyntaxTreeNode * mbGenerateNode);
	SemanticsBlockTerminate * ReadMBTerminate(SyntaxTreeNode * mbTerminateNode);
	SemanticsBlockAdvance * ReadMBAdvance(SyntaxTreeNode * mbAdvanceNode);
	SemanticsBlockEnter * ReadMBEnter(SyntaxTreeNode * mbEnterNode);
	SemanticsBlockLeave * ReadMBLeave(SyntaxTreeNode * mbLeaveNode);
	SemanticsBlockSeize * ReadMBSeize(SyntaxTreeNode * mbSeizeNode);
	SemanticsBlockRelease * ReadMBRelease(SyntaxTreeNode * mbReleaseNode);
	SemanticsBlockInqueue * ReadMBInqueue(SyntaxTreeNode * mbInqueueNode);
	SemanticsBlockOutqueue * ReadMBOutqueue(SyntaxTreeNode * mbOutqueueNode);
	SemanticsBlockArrive * ReadMBArrive(SyntaxTreeNode * mbArriveNode);
	SemanticsBlockDepart * ReadMBDepart(SyntaxTreeNode * mbDepartNode);
	SemanticsBlockModelInstance * ReadMBModelInstance(SyntaxTreeNode * mbModelInstanceNode);
	SemanticsBlockGoto * ReadMBGoto(SyntaxTreeNode * mbGotoNode);
	SemanticsBlockIf * ReadMBIf(SyntaxTreeNode * mbIfNode, int parentContext);
	SemanticsModelName * ReadMBModelName(SyntaxTreeNode * mbModelNameNode); // not sure ???
	SemanticsBlockWait * ReadMBWait(SyntaxTreeNode * mbWaitNode, int parentContext);
	SemanticsBlockJoinGroup * ReadMBJoinGroup(SyntaxTreeNode * mbJoinGroupNode);
	SemanticsBlockLeaveGroup * ReadMBLeaveGroup(SyntaxTreeNode * mbLeaveGroupNode);
	SemanticsBlockCreate * ReadMBCreate(SyntaxTreeNode * mbCreateNode);
	SemanticsBlockSplit * ReadMBSplit(SyntaxTreeNode * mbSplitNode);
	SemanticsBlockGather * ReadMBGather(SyntaxTreeNode * mbGatherNode);
	SemanticsBlockExecute * ReadMBExecuter(SyntaxTreeNode * mbExecuteNode);




	// FOR SIMULATION: ReadSim  = ReadSimulationStatement
	SemanticsSimulationStatement * ReadSimulationStatement(SyntaxTreeNode * simulationStatementNode);

	SemanticsSimStatConfiguration * ReadSimConfiguration(SyntaxTreeNode * simStConfigurationNode);
	SemanticsSimStatRun * ReadSimRun(SyntaxTreeNode * simStRunNode);
	SemanticsSimStatClear * ReadSimClear(SyntaxTreeNode * simStClear);
	SemanticsSimStatReset * ReadSimReset(SyntaxTreeNode * simStReset);
	


    // gathering context
	SemanticsContext * GetCurrentContext(SyntaxTreeNode * nodeUsings);
	int SaveContext(SemanticsContext * context);
	int SaveContext(SemanticsContext * context, int parrentContext);


#ifdef DEBUG
	
	void DebugXMLOutput(FILE * fo, LexicUnits * lus);
	void DebugXMLOutputFlatten(FILE * fo, LexicUnits * lus);
	
	static void DebugOutputNameFromTable(FILE * fo, GenericTable<int> * name, LexicUnits * lus);

#endif

private:
	GenericTable<SemanticsContext> * contexts;

};



#endif
